package com.kingyun.gpsinspection.purificationservice.services.tdm.innerservice.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cqhilink.api.common.utils.UniqueUtil;
import com.kingyun.gpsinspection.purificationservice.common.activiti.ActivitiConstants;
import com.kingyun.gpsinspection.purificationservice.common.utils.FileTypeUtil;
import com.kingyun.gpsinspection.purificationservice.dao.mapper.iam.accessory.OrganizationMapper;
import com.kingyun.gpsinspection.purificationservice.dao.mapper.tdm.*;
import com.kingyun.gpsinspection.purificationservice.facade.model.File;
import com.kingyun.gpsinspection.purificationservice.facade.model.jsm.EmployeeVo;
import com.kingyun.gpsinspection.purificationservice.facade.model.jsm.RedisValue;
import com.kingyun.gpsinspection.purificationservice.facade.model.som.User;
import com.kingyun.gpsinspection.purificationservice.facade.model.tdm.*;
import com.kingyun.gpsinspection.purificationservice.facade.service.activiti.base.WorkFlowService;
import com.kingyun.gpsinspection.purificationservice.facade.service.jsm.employee.JsmEmployeeService;
import com.kingyun.gpsinspection.purificationservice.facade.service.tdm.DailyThingsService;
import com.kingyun.gpsinspection.purificationservice.facade.service.tdm.IBMBPMService;
import com.kingyun.gpsinspection.purificationservice.facade.service.tdm.WorkOrderService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by jiangjx on 2017/5/4.
 */
public class DailyThingsServiceImpl implements DailyThingsService {
    public Logger logger = LoggerFactory.getLogger(this.getClass());

    public static final String PROCESS_KEY1 = "daily";

    @Autowired
    public IBMBPMService ibmbpmService;
    @Autowired
    private TdmTaskRelationMapper tdmTaskRelationMapper;
    @Autowired
    private DailyThingsMapper dailyThingsMapper;
    @Autowired
    private TdmFileMapper tdmFileMapper;
    @Autowired
    public TaskLinkMapper taskLinkMapper;
    @Autowired
    private WorkOrderService workOrderService;
    @Autowired
    public TdmWorkOrderMapper tdmWorkOrderMapper;
    @Autowired
    public WorkOrderEmployeeMapper workOrderEmployeeMapper;
    @Autowired
    private WorkFlowService workFlowService;
    @Autowired
    private OrganizationMapper organizationMapper;
    @Autowired
    private JsmEmployeeService jsmEmployeeService;

    /**
     * 保存信息
     *
     * @param employeeVo
     * @param dailyThingsVo
     * @param uploadFiles
     * @param deletedFiles
     * @param workOrderList
     * @return returnCode99:当前用户不属于作业区无法创建流程
     */
    @Override
    public int save(EmployeeVo employeeVo, DailyThingsVo dailyThingsVo, String uploadFiles, String deletedFiles, List<WorkOrderVo> workOrderList) {
        if (null == dailyThingsVo) return 0;
        //第一步：保存任务信息
        //注意对象做方法参数传的是引用：此方法中设置的值，在此方法结束后，相应对象的值也改变
        saveBean(employeeVo, dailyThingsVo);

        //第二步：保存附件；根据任务信息
        saveAttach(dailyThingsVo, uploadFiles, deletedFiles);

        saveTaskLinkWorkOrder(employeeVo, dailyThingsVo, workOrderList);

        Map map = new HashMap<>();
        try {
            workFlowService.startProcessInstanceByKey(PROCESS_KEY1, dailyThingsVo.getDailythingsId(), map, employeeVo.getEmployeeId());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 根据工单来获取审批人员信息
     */
    private Map achievePersons(List<WorkOrderVo> workOrderList) {
        Map map = new HashMap<>();
        List<String> names = new ArrayList<>();
        for (WorkOrderVo workOrderVo : workOrderList) {
            if (null != workOrderVo.getOrgId() && workOrderVo.getOrgId() != "") {
                List<User> list = organizationMapper.queryUsersByOrgId(workOrderVo.getOrgId());
                names.addAll(list.stream().map(User::getUserId).collect(Collectors.toList()));
            } else if (null != workOrderVo.getUserId() && workOrderVo.getUserId() != "") {
                if (workOrderVo.getUserId().contains(",")) {
                    String[] ids = workOrderVo.getUserId().split(",");
                    for (String id : ids) {
                        names.add(id);
                    }
                } else {
                    names.add(workOrderVo.getUserId());
                }
            }
        }
        map.put(ActivitiConstants.MANUAL_PERSON, names);
        return map;
    }

    /**
     * 保存日常事务任务对象
     *
     * @param employeeVo
     * @param dailyThingsVo
     * @return
     */
    public int saveBean(EmployeeVo employeeVo, DailyThingsVo dailyThingsVo) {
        //新增发起任务信息
        dailyThingsVo.setDailythingsId(UniqueUtil.uuid());
        dailyThingsVo.setCreateUserId(employeeVo.getEmployeeId());
        dailyThingsVo.setModifyUserId(employeeVo.getEmployeeId());
        dailyThingsVo.setCreateTime(new Date());
        dailyThingsVo.setModifyTime(new Date());
        //-1 正在审核；1 审核通过；0审核不通过
        dailyThingsVo.setAuditStatus((short) -1);
        //状态0正常；1是删除
        dailyThingsVo.setIsDelete((short) 0);
        //状态1是启用；0是关闭
        dailyThingsVo.setIsEnable(dailyThingsVo.getIsEnable() == null ? (short) 1 : dailyThingsVo.getIsEnable());
        //1 审核处理中；2 执行中；3 已完成
        dailyThingsVo.setTaskStatus((short) 1);
        int a = dailyThingsMapper.insertSelective(dailyThingsVo);
        return a;
    }

    /**
     * 根据Bean的信息保存附件（新增和删除）
     *
     * @param dailyThingsVo
     * @param uploadFiles
     * @return
     */
    public int saveAttach(DailyThingsVo dailyThingsVo, String uploadFiles, String deletedFiles) {
        int a = 0;
        //保存附件
        if (StringUtils.isNotBlank(uploadFiles)) {
            //强制转换成集合
            List<File> listFiles = JSON.parseArray(uploadFiles, File.class);
            //重新设置附件属性
            for (int i = 0; i < listFiles.size(); i++) {
                File _file = listFiles.get(i);
                //设置主键
                _file.setFileId(UniqueUtil.uuid());
                //设置业务数据id
                _file.setBusinessId(dailyThingsVo.getDailythingsId());
                _file.setFileType((short) FileTypeUtil.getFileTypeByFileName(_file.getFileName()));
            }
            //必须判断非空
            if (listFiles != null && listFiles.size() > 0) {
                a = tdmFileMapper.insertByList(listFiles);
            }
        }
        //需要删除的附件信息
        if (StringUtils.isNotBlank(deletedFiles)) {
            //强制转换成集合
            List<File> listFiles = JSON.parseArray(deletedFiles, File.class);
            if (null != listFiles && listFiles.size() > 0) {
                for (File file : listFiles) {
                    a += tdmFileMapper.deleteByPrimaryKey(file.getFileId());
                }
            }
        }
        return a;
    }

    /**
     * 保存任务相关信息：先保存任务环节，再保存工单
     *
     * @param employeeVo
     * @param dailyThingsVo
     * @param wrokOrderList
     * @return
     */
    public void saveTaskLinkWorkOrder(EmployeeVo employeeVo, DailyThingsVo dailyThingsVo, List<WorkOrderVo> wrokOrderList) {
        //保存工单：后
        workOrderService.saveWorkOrderList(employeeVo, dailyThingsVo.getDailythingsId(), dailyThingsVo.getTaskType(), wrokOrderList);
        dailyThingsVo.setAuditStatus((short) 1);
        dailyThingsMapper.updateAuditStatusById(dailyThingsVo);
        //进入现场操作：更新任务状态为执行中
        dailyThingsMapper.updateTaskStatusExecutedById(dailyThingsVo);
        //进入现场操作：所有工单状态改为可用
        tdmWorkOrderMapper.updateStatusEnableByTaskId(dailyThingsVo.getDailythingsId());
    }

    /**
     * 根据任务实例ID查询任务表和任务环节表
     *
     * @param piPiid
     * @return
     */
    @Override
    public DailyThingsVo findVoByPiPiid(String piPiid) {
        if (StringUtils.isBlank(piPiid))
            return null;
        return dailyThingsMapper.findVoByPiPiid(piPiid);
    }

    /**
     * 现场操作
     *
     * @param redisValue
     * @param employeeVo
     * @param dailyThingsVo
     * @param taskLink
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public int saveBySpotOperation(RedisValue redisValue, EmployeeVo employeeVo, DailyThingsVo dailyThingsVo, TaskLink taskLink) {
        if (null == taskLink) {
            return 0;
        }
        String result = ibmbpmService.completeTask(redisValue.getLoginName(), redisValue.getPassWord(), taskLink.getTkiid(), null);
        //标志变量
        int a = 0;
        //处理返回值为空串：执行了但是没有返回值
        if ("".equals(result)) {
            logger.info("完成“" + taskLink.getTaskLinkName() + "”返回值为空串！");
        } else {
            //获得返回值
            JSONObject resultObj = JSONObject.parseObject(result);
            if (resultObj != null) {
                String status = resultObj.get("status").toString();
                //开始流程成功
                if (null != status && status.equals("200")) {
                    saveTaskLinkWorkOrder(employeeVo, dailyThingsVo, null);
                } else {
                    logger.error("完成“" + taskLink.getTaskLinkName() + "”返回状态非200！");
                }
            } else {
                logger.error("完成“" + taskLink.getTaskLinkName() + "”返回值非json字符串！");
            }
        }
        return a;
    }

    /**
     * 保存分析处理的关联的维护保养任务
     *
     * @param employeeVo
     * @param dailyThingsVo
     * @param uploadFiles
     * @param deletedFiles
     * @param workOrderList
     * @param analysisProcessId
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public int saveRelation(EmployeeVo employeeVo, DailyThingsVo dailyThingsVo, String uploadFiles, String deletedFiles, List<WorkOrderVo> workOrderList, String analysisProcessId) {
        if (null == dailyThingsVo)
            return 0;
        int a = 0;
        dailyThingsVo.setNode((short) -1);
        //注意对象做方法参数传的是引用：此方法中设置的值，在此方法结束后，相应对象的值也改变
        a += saveBean(employeeVo, dailyThingsVo);

        TaskRelation taskRelation = new TaskRelation();
        taskRelation.setTaskRelationId(UniqueUtil.uuid());
        taskRelation.setMasterTaskId(analysisProcessId);
        taskRelation.setMasterTaskType((short) 5);
        taskRelation.setRelatedTaskId(dailyThingsVo.getDailythingsId());
        taskRelation.setRelatedTaskType(dailyThingsVo.getTaskType());
        a += tdmTaskRelationMapper.insert(taskRelation);

        //根据任务信息保存工单
        a += saveWorkOrderList(employeeVo, dailyThingsVo, workOrderList);

        //根据任务信息保存附件
        a += saveAttach(dailyThingsVo, uploadFiles, deletedFiles);

        return a;
    }

    /**
     * 根据任务信息保存工单
     *
     * @param employeeVo
     * @param dailyThingsVo
     * @param workOrderList
     * @return
     */
    public int saveWorkOrderList(EmployeeVo employeeVo, DailyThingsVo dailyThingsVo, List<WorkOrderVo> workOrderList) {
        int a = 0;

        if (workOrderList != null && workOrderList.size() > 0) {
            //注意思路：先删除后新增
            List<WorkOrder> oldWorkOrderList = tdmWorkOrderMapper.findListByTaskId(dailyThingsVo.getDailythingsId());

            //先根据工单Id删除工单和人员的关系表
            if (oldWorkOrderList != null && oldWorkOrderList.size() > 0) {
                for (WorkOrder oldWorkOrder : oldWorkOrderList) {
                    if (oldWorkOrder != null && oldWorkOrder.getWorkOrderId() != null) {
                        a += workOrderEmployeeMapper.deleteByWorkOrderId(oldWorkOrder.getWorkOrderId());
                    }
                }
            }
            //再根据任务Id删除该任务对应的工单：
            a += tdmWorkOrderMapper.deleteByTaskId(dailyThingsVo.getDailythingsId());

            //重要方法：给List中的元素回设置
            for (WorkOrderVo workOrder : workOrderList) {
                //重新设置主键ID
                workOrder.setWorkOrderId(UniqueUtil.uuid());
                workOrder.setTaskId(dailyThingsVo.getDailythingsId());
                //无法保存任务环节ID
                workOrder.setTaskType(dailyThingsVo.getTaskType());
                workOrder.setCreateUserId(employeeVo.getEmployeeId());
                workOrder.setModifyUserId(employeeVo.getEmployeeId());
                //工单状态：-1预处理，0创建，1作业条件检查，2作业前准备，3操作申请（关键操作--才会申请），4审核通过，5审核不通过，6已经完成，7已关闭
                workOrder.setStatus((short) -1);
                //1是删除；0是正常
                workOrder.setIsDelete((short) 0);
                //0未下载；已经下载
                workOrder.setIsDownload((short) 0);
                //0无法完成；1可以完成
                workOrder.setCanFinish((short) 1);
                //0未确认；1已经确认
                workOrder.setConfirmStatus((short) 0);

                //先保存工单
                a += tdmWorkOrderMapper.insertNew(workOrder);

                //保存工单和人员的关系表：
                if (workOrder.getUserId() != null) {
                    String[] array = workOrder.getUserId().split(",");
                    if (array != null && array.length > 0) {
                        for (String str : array) {
                            if (StringUtils.isNotBlank(str)) {
                                WorkOrderEmployee workOrderEmployee = new WorkOrderEmployee();
                                workOrderEmployee.setWorkOrderEmployeeId(UniqueUtil.uuid());
                                workOrderEmployee.setWorkOrderId(workOrder.getWorkOrderId());
                                workOrderEmployee.setEmployeeId(str);
                                a += workOrderEmployeeMapper.insert(workOrderEmployee);
                            }
                        }
                    }
                }
            }
        }
        return a;
    }

    /**
     * 修改分析处理关联的维护保养任务页面：不走BPM
     *
     * @param employeeVo
     * @param dailyThingsVo
     * @param uploadFiles
     * @param deletedFiles
     * @param workOrderVoList
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public int updateRelation(EmployeeVo employeeVo, DailyThingsVo dailyThingsVo, String uploadFiles, String deletedFiles, List<WorkOrderVo> workOrderVoList) {
        if (null == dailyThingsVo)
            return 0;
        //标志变量
        int a = 0;
        //第一步：更新任务信息；修改人必填
        dailyThingsVo.setModifyUserId(employeeVo.getEmployeeId());
        a += dailyThingsMapper.updateByPrimaryKeyNew(dailyThingsVo);
        //第二步：更新附件信息：新增+删除
        a += saveAttach(dailyThingsVo, uploadFiles, deletedFiles);
        //第三步：更新工单信息：先删除，后新增
        a += saveWorkOrderList(employeeVo, dailyThingsVo, workOrderVoList);
        return a;
    }

    /**
     * 根据主键查询bean
     *
     * @param dailythingsId
     * @return
     */
    @Override
    public DailyThingsVo queryBeanById(String dailythingsId) {
        if (StringUtils.isBlank(dailythingsId))
            return null;
        return dailyThingsMapper.selectByPrimaryKey(dailythingsId);
    }

    /**
     * 发起BPM流程：和save方法相似
     *
     * @param redisValue
     * @param employeeVo
     * @param dailyThingsVo
     * @param workOrderVoList
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public int launchBPM(RedisValue redisValue, EmployeeVo employeeVo, DailyThingsVo dailyThingsVo, List<WorkOrderVo> workOrderVoList) {
        int a = 0;
        //开始流程：需要任务类型
        String result = ibmbpmService.openBPM(employeeVo, dailyThingsVo.getTaskType(), redisValue.getLoginName(), redisValue.getPassWord(), null);
        //如果没有权限直接返回99
        if (result.equals("WorkSpaceError")) {
            return 99;
        }
        //获得返回值
        JSONObject resultObj = JSONObject.parseObject(result);
        if (resultObj != null) {
            String status = (String) resultObj.get("status");
            //开始流程成功
            if (status != null && status.equals("200")) {
                //获取data属性的值
                JSONObject dataObj = (JSONObject) resultObj.get("data");
                //获取tasks属性的值：只有一个元素的数组，元素包含流程实例id和第一个节点的任务id
                JSONArray itemsArray = (JSONArray) dataObj.get("tasks");
                JSONObject ob = (JSONObject) itemsArray.get(0);//得到json对象
                //piid这里是列名称，获取json对象中列名为piid的值
                String piid = ob.getString("piid");
                //tkiid这里是列名称，获取json对象中列名为tkiid的值
                String tkiid = ob.getString("tkiid");
                //name是列名称，获取json对象中列名为name的值
                String name = ob.getString("name");
                //执行第一个任务节点
                result = ibmbpmService.completeTask(redisValue.getLoginName(), redisValue.getPassWord(), tkiid, null);
                //获得返回值
                resultObj = JSONObject.parseObject(result);
                if (resultObj != null && !"".equals(resultObj)) {
                    status = (String) resultObj.get("status");
                    //完成任务成功
                    if (status != null && status.equals("200")) {
                        //第一步：更新流程实例ID和当前节点
                        dailyThingsVo.setFlowId(piid);
                        dailyThingsVo.setNode((short) 0);
                        //CREATE_TIME重新赋值：代表任务发起时间，而不是任务新建时间
                        dailyThingsVo.setCreateTime(new Date());
                        a += dailyThingsMapper.updateByPrimaryKeySelective(dailyThingsVo);
                        //第二步：保存任务环节；修改工单需要保存；
                        TaskLink taskLink = new TaskLink();
                        taskLink.setPiPiid(piid);//流程实例ID
                        taskLink.setTkiid(tkiid);//任务节点ID
                        taskLink.setTaskLinkName(name); //任务节点名称
                        //第一个节点默认通过
                        taskLink.setAuditStatus((short) 1);
                        //任务指派人可以修改工单，但不能修改任务基础信息
                        saveTaskLinkWorkOrder(employeeVo, dailyThingsVo, workOrderVoList);
                    } else {
                        logger.error("完成维护保养流程第一个任务节点失败！");
                    }
                } else {
                    logger.error("完成维护保养流程第一个任务节点无返回值！");
                }

            } else {
                logger.error("发起维护保养流程失败！");
            }
        } else {
            logger.error("发起维护保养流程无返回值！");
        }
        return a;
    }

    /**
     * 查询任务信息（包含关联信息）
     *
     * @param taskId
     * @return
     */
    @Override
    public DailyThingsVo queryVoById(String taskId) {
        if (StringUtils.isBlank(taskId))
            return null;
        return dailyThingsMapper.selectByPrimaryKeyNew(taskId);
    }
}
